/*
*	0X43 0X57 | SLAVE ADD | FUNC_CODE1    FUNC_CODE1  |   LEN   |  DATA     |  0X45  0X53                          			
*	  帧头	     从机地址     功能码1      功能码2       字节数	   数据内容      帧尾
*
*帧头：43H 57H；
*长度：数据字节长度；
*主功能码：用于区分操作对象或者操作类型；
*子功能码：用于区分具体操作；
*数据：需要发送的数据；
*帧尾：45H 53H (非校验，此数据固定)；
*CRC校验目的地址到CRC前一位的数据；
*
*/

#include "RS485Handle.h"
#include "saecrc.h"
#include "MidUsart.h"
#include "event_queue_Handle.h"
#include "SEGGER_RTT.h"

static void _RS485Send(uint8_t *Buf, uint8_t num);
static void _BMSFaultWrite(ENU_FAULT_TYPE fault_type, ENU_EVT_OP evt_op);

static BmsMsg  gbmsmsg[BSM_NUM];

#define BMS1_ADDR	0
#define BMS2_ADDR	1


/**
*	装载帧头
*  Buf: 整个帧的起始位置
*  num：数据数量
*/
static void loadHead(uint8_t *Buf)
{
	*Buf 		= RS485_HEAD1;
	*(Buf +1) 	= RS485_HEAD2;
}

/**
*	装载CRC 和帧尾
*  dataBuf: 存储数据内容的缓冲区
*  dataNum：数据数量
*/
static void loadCrc8AndTail(uint8_t *dataBuf, uint8_t dataNum)
{	
	*(dataBuf + dataNum) = SaeCrcCal(dataBuf,dataNum);
	*(dataBuf + dataNum +1) = RS485_TAIL1;
	*(dataBuf + dataNum +2) = RS485_TAIL2;
}



// 根据BMS地址填充BMS相关故障信息
static void BMSOfflineEventDo(uint8_t add, ENU_EVT_OP op)
{
	switch(add)
	{
		case BMS1_ADDR:
			_BMSFaultWrite(FAULT_BMS1_OFFLINE, op);
			break;
		case BMS2_ADDR:
			_BMSFaultWrite(FAULT_BMS2_OFFLINE, op);
		break;
		
	}
}



/**
 * 检测BMS通信 离线时间
 * buf 要解析的报文
*/
void BmsOfflineCheck(uint8_t addr)
{
	if(gbmsmsg[addr].OfflinCount != 0XFF)
	{
		gbmsmsg[addr].OfflinCount += 1;
	}
		
	if(gbmsmsg[addr].OfflinCount > 30 && gbmsmsg[addr].OfflinStatus != TRUE)
	{
		DEBUG_LOG_INFO(DEBUG_LEVEL_2, "  *******BMS OFFLINE*******  \n");
		gbmsmsg[addr].OfflinStatus = TRUE;
		BMSOfflineEventDo(addr, EVT_ADD);
	}
}
/**
 * BMS离线计数清空
 * 0 通信失败
 * 1 成功
 * buf 要解析的报文
*/
static void BmsOfflineCountClear(uint8_t addr)
{
	if(gbmsmsg[addr].OfflinStatus == TRUE)
	{
		BMSOfflineEventDo(addr, EVT_DELET);
	}
	
	gbmsmsg[addr].OfflinCount = 0;
	gbmsmsg[addr].OfflinStatus = FALSE;	
}


//BMS 充电故障
static void BMSChargeFaultEventDo(uint8_t add, ENU_EVT_OP op)
{
	switch(add)
	{
		case BMS1_ADDR:
			_BMSFaultWrite(FAULT_BMS1_CHARGE, op);
			break;
		case BMS2_ADDR:
			_BMSFaultWrite(FAULT_BMS2_CHARGE, op);
		break;
		
	}
}

/* 检查 充电器故障 */
static void CheckChargeFault(uint8_t addr)
{
	if(gbmsmsg[addr].ChargerStatus == 0X02 && gbmsmsg[addr].ChargeFaultStatus == 0)//检测充电状态两位: 00：充电状态，01:备电状态，02：故障状态
	{			
		BMSChargeFaultEventDo(addr, EVT_ADD);
		gbmsmsg[addr].ChargeFaultStatus = 1;
	}
	if(gbmsmsg[addr].ChargerStatus == 0 && gbmsmsg[addr].ChargeFaultStatus == 1)
	{
		BMSChargeFaultEventDo(addr, EVT_DELET);
		gbmsmsg[addr].ChargeFaultStatus = 0;	
	}

}


//BMS 传递出的故障
static void BMSGiveFaultEventDo(uint8_t add, ENU_EVT_OP op)
{
	switch(add)
	{
		case BMS1_ADDR:
			_BMSFaultWrite(FAULT_BMS1, op);
			break;
		case BMS2_ADDR:
			_BMSFaultWrite(FAULT_BMS2, op);
		break;
		
	}

}

/*  检查BMS故障  */
static void CheckBmsFaults(uint8_t addr)
{	
	if(gbmsmsg[addr].BmsFaultCount != 0 && gbmsmsg[addr].BmsFaultStatus == 0 )
	{		
		BMSGiveFaultEventDo(addr, EVT_ADD);
		gbmsmsg[addr].BmsFaultStatus = 1;
		
	}
	else if(gbmsmsg[addr].BmsFaultCount == 0 && gbmsmsg[addr].BmsFaultStatus == 1)
	{
		BMSGiveFaultEventDo(addr, EVT_DELET);//抛 删除故障事件
		gbmsmsg[addr].BmsFaultStatus = 0;
	}
	gbmsmsg[addr].BmsFaultCount = 0;  // 清零
}


//BMS 电量低事件抛出
static void BMSLowFaultEventDo(uint8_t add, ENU_EVT_OP op)
{
	switch(add)
	{
		case BMS1_ADDR:
			_BMSFaultWrite(FAULT_BAT_LOW, op);
			break;
		case BMS2_ADDR:
			_BMSFaultWrite(FAULT_BAT_LOW, op);
		break;
		
	}
}


#define LOW_POWER_VAL	240  // val/10 = 24.0V
static void BatLowPowerFault(uint8_t addr)
{
	if(gbmsmsg[addr].TotalVoltage < LOW_POWER_VAL && gbmsmsg[addr].BMSBatLowFlag == 0)//检测充电状态两位: 00：充电状态，01:备电状态，02：故障状态
	{			
		BMSLowFaultEventDo(addr, EVT_ADD);
		gbmsmsg[addr].BMSBatLowFlag = 1;
	}
	if(gbmsmsg[addr].TotalVoltage >= LOW_POWER_VAL && gbmsmsg[addr].BMSBatLowFlag == 1)
	{
		BMSLowFaultEventDo(addr, EVT_DELET);
		gbmsmsg[addr].BMSBatLowFlag = 0;	
	}
}








/**
 * 对01H回复的报文进行填充结构体，分析
 * buffer 经过解析函数得到的报文内容
*/
static void BmsAnsMsgHandle(uint8_t addr, uint8_t *buffer)
{	
	gbmsmsg[addr].SOC = ((buffer[0] <<8) + buffer[1]);	
	gbmsmsg[addr].TotalVoltage = (buffer[2] << 8) +  buffer[3];	
	gbmsmsg[addr].HighestCellVoltage = (buffer[4] << 8) + buffer[5];
	gbmsmsg[addr].LowestCellVoltage= (buffer[6] << 8) + buffer[7];
	gbmsmsg[addr].Voltage = (buffer[8] << 8) + buffer[9];	
	gbmsmsg[addr].Temperature= (buffer[10] << 8) + buffer[11];
	gbmsmsg[addr].ChargerStatus= (buffer[12] << 8) + buffer[13];

	for(int i = 0; i <= 8;i++)
	{						//填充故障
		gbmsmsg[addr].Fault[i] = buffer[14+i];
		
		if(gbmsmsg[addr].Fault[i] != 0 )
		{			
			gbmsmsg[addr].BmsFaultCount ++;
		}			
	}
	gbmsmsg[addr].MajorVersion = buffer[23];				//主次版本号
	gbmsmsg[addr].MinorVersion = buffer[24];	
	
	CheckChargeFault(addr);
	CheckBmsFaults(addr);
	BatLowPowerFault(addr);
//	DEBUG_LOG_INFO(DEBUG_LEVEL_2, "  add %d ,gbmsmsg[addr].SOC %d \n",addr, gbmsmsg[addr].SOC);

	
	
}


/**
 * 请求地址回复报文解析
 * 首先检测是否有报文回复
 * buffer：报文解析通过后接收到的数据
*/

static void AddrAnsMsgHandle(uint8_t addr, uint8_t *buffer)
{
	
}


void RS485CmdHandle(uint8_t *buf)
{	
	UINT8 SlaveAdd = buf[0] -1;
	UINT8 MainFuncCode = buf[1];
	
	BmsOfflineCountClear(SlaveAdd);
	
    switch (MainFuncCode)
    {
        case MAIN_BMS_FUNCTION:
			BmsAnsMsgHandle(SlaveAdd, &buf[4]);	//数据位
            break;
		
        case MAIN_ADDR_FUNCTION:
		    AddrAnsMsgHandle(SlaveAdd, &buf[4]);	
            break;
		
        default:
          break;  
    }
}



/*  抛BMS 故障 */
static void _BMSFaultWrite(ENU_FAULT_TYPE fault_type, ENU_EVT_OP evt_op)
{
	EvtFaultWrite(fault_type, evt_op);
			DEBUG_LOG_INFO(DEBUG_LEVEL_2, "  *******BMS FAULT*******  \n");

}


static void _RS485Send(uint8_t *Buf, uint8_t num)
{
	RS485_send(Buf , num);

}



/* 获得当前电量   */
UINT16 GetSOC(UINT8 SlaveAddr)
{
	return (gbmsmsg[SlaveAddr].SOC / 10); // 取百分比
}


/************************send************************************/


/**
 * 请求 BMS的状态数据 
*/

void BmsAskMsgSend (UINT8 SlaveAddr) //Bms
{			
	uint8_t BmsMsgbuf[9] = {0};

	loadHead(BmsMsgbuf);				//填充帧头       
	BmsMsgbuf[2] = 		SlaveAddr+1;	//从机地址
	BmsMsgbuf[3] = 		MAIN_BMS_FUNCTION;	//主功能吗
	BmsMsgbuf[4] = 		SECONDARY_FUNCTION;//子功能吗
	BmsMsgbuf[5] = 		BMS_DATA_LENGTH;		//填充数据长度

	
	BmsMsgbuf[6] = SaeCrcCal(BmsMsgbuf,6);
	BmsMsgbuf[7] = RS485_TAIL1;
	BmsMsgbuf[8] = RS485_TAIL2;
	
	//loadCrc8AndTail(&BmsMsgbuf[0],6);			//帧尾
	
	_RS485Send(BmsMsgbuf,sizeof(BmsMsgbuf));
	
}



/**
 * 上位机发送设置地址
 * buff：地址  1~247
 */
//void loadDebugAskMsgSend (uint8_t IdSet)
//{			// 设置从设备地址
//	uint8_t BmsMsgbuf[10];

//	loadHead(BmsMsgbuf);				//填充帧头
//	BmsMsgbuf[2] = 		SLAVE_ADDRESS;	//从机地址
//	BmsMsgbuf[3] = 		MAIN_ADDR_FUNCTION;	//主功能吗
//	BmsMsgbuf[4] = 		SECONDARY_FUNCTION;	//子功能吗
//	BmsMsgbuf[5] = 		ADDR_DATA_LENGTH;			//填充数据长度
//	BmsMsgbuf[6] =      IdSet ;				//数据内容
//	
//	loadCrc8AndTail(BmsMsgbuf,5);			//帧尾

//	_RS485Send(BmsMsgbuf,sizeof(BmsMsgbuf));

//}












